<?php
namespace App\Pay\Gateway;

use App\Pay\Config\Config;
use App\Pay\Contracts\GatewayInterface;
use App\Pay\Exceptions\InvalidArgumentException;
use App\Pay\Exceptions\InvalidSignException;
use GuzzleHttp\Client;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class Wechat implements GatewayInterface
{

    /**
     * 普通模式.
     */
    const MODE_NORMAL = 'normal';

    /**
     * 沙箱模式.
     */
    const MODE_DEV = 'dev';

    /**
     * 香港钱包 API.
     */
    const MODE_HK = 'hk';

    /**
     * 境外 API.
     */
    const MODE_US = 'us';

    /**
     * Const url.
     */
    const URL = [
        self::MODE_NORMAL => 'https://api.mch.weixin.qq.com/',
        self::MODE_DEV    => 'https://api.mch.weixin.qq.com/sandboxnew/',
        self::MODE_HK     => 'https://apihk.mch.weixin.qq.com/',
        self::MODE_US     => 'https://apius.mch.weixin.qq.com/',
    ];

    /**
     * @var Config
     */
    protected $config;

    /**
     * @var array
     */
    protected $payload = [];

    /**
     * Wechat constructor.
     * @param Config $config
     */
    public function __construct(Config $config)
    {
        $this->config = $config;
        \App\Pay\Gateway\Wechat\Request::instance()->setConfig($this->config);
    }

    /**
     * @param string $endpoint
     * @param array $params
     * @return mixed
     */
    public function pay(string $endpoint, array $params)
    {
        $gatewayClass = get_class($this) . '\\' . ucfirst($endpoint) . 'Gateway';
        $this->payload = array_merge([
            'appid'             => $this->config->get('mp_appid'),
            'mch_id'            => $this->config->get('mch_id'),
            'nonce_str'         => uniqid(),
            'spbill_create_ip'  => Request::createFromGlobals()->getClientIp(),
            'notify_url'        => $this->config->get('notify_url'),
            'trade_type'        => '',
            'sign'              => ''
        ], $params);
        return (new $gatewayClass())->pay($this->payload);
    }

    public function cancel(array $params)
    {
        // TODO: Implement cancel() method.
    }

    public function close(array $params)
    {
        // TODO: Implement close() method.
    }

    public function query(array $params)
    {
        // TODO: Implement query() method.
    }

    public function refund(array $params)
    {
        // TODO: Implement refund() method.
    }

    public function refundQuery(array $params)
    {
        // TODO: Implement refundQuery() method.
    }

    /**
     * @param null $content
     * @param bool $isRefund
     * @return array|mixed
     * @throws InvalidArgumentException
     * @throws InvalidSignException
     */
    public function verify($content = null, $isRefund = false)
    {
        if (is_null($content)) {
            $content = $content ?? Request::createFromGlobals()->getContent();
        }
        $data = \App\Pay\Gateway\Wechat\Request::xmlToArr($content);
        if (\App\Pay\Gateway\Wechat\Request::sign($data) === $data['sign']) {
            return $data;
        }
        throw new InvalidSignException('签名错误');
    }

    /**
     * @return mixed|Response
     * @throws InvalidArgumentException
     */
    public function success()
    {
        return new Response(
            \App\Pay\Gateway\Wechat\Request::arrToXml(['return_code' => 'SUCCESS', 'return_msg' => 'OK']),
            200,
            ['Content-Type' => 'application/xml']
        );
    }
}
